# MICROWIDGET - A simple widget library wrapper around MICROC

from microc import *

# Terminal - Root widget, not technically a Widget.
class Terminal:
  def __init__(self, log=None):
    self.width = 40
    self.height = 12
    self.buffer = []
    
    col = 0
    row = 0
    while row < self.height:
      self.buffer.append([])
      col = 0
      while col < self.width:
        self.buffer[row].append((' ',CWHITE,CBLACK))
        col += 1
      
      row += 1
    
    self.csr = (0,0)
    self.fg = CWHITE
    self.bg = CBLACK
    self.doscrl = True
    self.children = []
    self.log = log
  
  def logmsg(self, msg):
    if self.log != None:
      self.log.write(msg)
  
  def clear(self, ch=" ", fg=CWHITE, bg=CBLACK):
    #self.logmsg("clear : {0} : {1} : {2}\n".format(repr(ch), fg, bg))
    self.setcsr(0,0)
    row = 0
    col = 0
    while row < self.height:
      col = 0
      while col < self.width:
        self.setch(col, row, ch, fg, bg)
        col += 1
      row += 1
  
  def setch(self, col, row, ch=" ", fg=CWHITE, bg=CBLACK):
    #self.logmsg("setch : {0} : {1} : {2} : {3} : {4}\n".format(col, row, repr(ch), fg, bg))
    self.buffer[row][col] = (ch,fg,bg)
  
  # NOTE: This is not an input method
  def getch(self, col, row):
    #self.logmsg("getch : {0} : {1}\n".format(col, row))
    return self.buffer[row][col]
  
  def setcsr(self, col, row):
    #self.logmsg("setscr : {0} : {1}\n".format(col, row))
    self.csr = (col,row)
  
  def getcsr(self):
    #self.logmsg("getcsr\n")
    return self.csr
  
  def setfg(self, fg):
    #self.logmsg("setfg : {0}\n".format(fg))
    self.fg = fg
  
  def getfg(self):
    #self.logmsg("getfg\n")
    return self.fg
  
  def setbg(self, bg):
    #self.logmsg("setbg : {0}\n".format(bg))
    self.bg = bg
  
  def getbg(self):
    #self.logmsg("getbg\n")
    return self.bg
  
  def addch(self, ch):
    #self.logmsg("addch : {0}\n".format(repr(ch)))
    # Do special things depending
    # on specific characters.
    if ch == "\a":
      pass
    elif ch == "\b":
      self.setcsr(self.getcsr()[0]-1,self.getcsr()[1])
    elif ch == "\f":
      pass
    elif ch == "\n":
      self.setcsr(0,self.getcsr()[1]+1)
    elif ch == "\r":
      self.setcsr(0,self.getcsr()[1])
    elif ch == "\t":
      cx = self.getcsr()[0]
      cy = self.getcsr()[1]
      self.setcsr((cx+2) & ~(2-1),cy)
    elif ch == "\v":
      pass
    elif ch >= " ":
      c = self.getcsr()
      self.setch(c[0], c[1], ch, self.fg, self.bg)
      self.setcsr(c[0]+1,c[1])
    
    if self.getcsr()[0] >= self.width:
      self.setcsr(0,self.getcsr()[1]+1)
    
    if self.doscrl:
      self.scroll()
    else:
      if self.getcsr()[1] >= self.height:
        self.setcsr(self.getscr()[0],self.height)
  
  def scroll(self):
    #self.logmsg("scroll\n")
    c = self.getcsr()
    cx = c[0]
    cy = c[1]
    
    if cy >= self.height:
      row = 0
      while row < self.height - 1:
        col = 0
        while col < self.width:
          ch = self.getch(col, row+1)
          self.setch(col, row, ch[0], ch[1], ch[2])
          col += 1
        
        row += 1
      #while row < self.height - 1:
      #  self.buffer[row] = list(self.buffer[row+1])
      #  row += 1
      
      col = 0
      while col < self.width:
        self.setch(col, self.height-1, " ", self.fg, self.bg)
        col += 1
      self.setcsr(0,self.height-1)
  
  def addstr(self, s):
    #self.logmsg("addstr : {0}\n".format(repr(s)))
    idx = 0
    for idx in range(len(s)):
      self.addch(s[idx])
  
  def draw(self):
    #self.logmsg("draw\n")
    doshowcsr(False)
    col = 0
    row = 0
    while row < self.height:
      col = 0
      while col < self.width:
        setcsr(col+1, row+1)
        ch = self.getch(col,row)
        cprint(ch[0],ch[1],ch[2])
        col += 1
      
      row += 1
    
    setcsr(self.getcsr()[0]+1,self.getcsr()[1]+1)
    doshowcsr()
  
  def addchild(self, child):
    self.children.append(child)
  
  def removechild(self, child):
    self.children.remove(child)
  
  def drawall(self):
    for widget in self.children:
      widget.drawall()
    
    self.draw()

# Widget - Base Widgetclass
class Widget:
  def __init__(self, col, row, width, height):
    self.col = col
    self.row = row
    self.width = width
    self.height = height
    self.buffer = []
    self.parent = None
    
    col = 0
    row = 0
    while row < self.height:
      self.buffer.append([])
      col = 0
      while col < self.width:
        self.buffer[row].append((' ',CWHITE,CBLACK))
        col += 1
      
      row += 1
    
    self.fg = CWHITE
    self.bg = CBLACK
    self.children = []
  
  def clear(self, ch=" ", fg=CWHITE, bg=CBLACK):
    row = 0
    col = 0
    while row < self.height:
      col = 0
      while col < self.width:
        self.setch(col, row, ch, fg, bg)
        col += 1
      row += 1
  
  def setch(self, col, row, ch=" ", fg=CWHITE, bg=CBLACK):
    self.buffer[row][col] = (ch,fg,bg)
  
  def getch(self, col, row):
    return self.buffer[row][col]
  
  def setfg(self, fg):
    self.fg = fg
  
  def getfg(self):
    return self.fg
  
  def setbg(self, bg):
    self.bg = bg
  
  def getbg(self):
    return self.bg
  
  def draw(self):
    col = 0
    row = 0
    while row < self.height:
      col = 0
      while col < self.width:
        ch = self.getch(col, row)
        chc = ch[0]
        chfg = ch[1]
        chbg = ch[2]
        self.parent.setch(col+self.col,row+self.row,chc,chfg,chbg)
        col += 1
      
      row += 1
  
  def addchild(self, child):
    self.children.append(child)
  
  def removechild(self, child):
    self.children.remove(child)
  
  def drawall(self):
    for widget in self.children:
      widget.drawall()
    
    self.draw()

# SubTerminal - A Widget with identical functionality as a Terminal.
class SubTerminal(Widget):
  def __init__(self, col, row, width, height):
    Widget.__init__(self, col, row, width, height)
    self.csr = (0,0)
    self.doscrl = True
  
  def clear(self, ch=" ", fg=CWHITE, bg=CBLACK):
    Widget.clear(self,ch,fg,bg)
    self.setcsr(0,0)
  
  def setcsr(self, col, row):
    self.csr = (col,row)
  
  def getcsr(self):
    return self.csr
  
  def addch(self, ch):
    # Do special things depending
    # on specific characters.
    if ch == "\a":
      pass
    elif ch == "\b":
      self.setcsr(self.getcsr()[0]-1,self.getcsr()[1])
    elif ch == "\f":
      pass
    elif ch == "\n":
      self.setcsr(0,self.getcsr()[1]+1)
    elif ch == "\r":
      self.setcsr(0,self.getcsr()[1])
    elif ch == "\t":
      cx = self.getcsr()[0]
      cy = self.getcsr()[1]
      self.setcsr((cx+2) & ~(2-1),cy)
    elif ch == "\v":
      pass
    elif ch >= " ":
      c = self.getcsr()
      self.setch(c[0], c[1], ch, self.fg, self.bg)
      self.setcsr(c[0]+1,c[1])
    
    if self.getcsr()[0] >= self.width:
      self.setcsr(0,self.getcsr()[1]+1)
    
    if self.doscrl:
      self.scroll()
    else:
      if self.getcsr()[1] >= self.height:
        self.setcsr(self.getscr()[0],self.height)
  
  def scroll(self):
    c = self.getcsr()
    cx = c[0]
    cy = c[1]
    
    if cy >= self.height:
      row = 0
      while row < self.height - 1:
        col = 0
        while col < self.width:
          ch = self.getch(col, row+1)
          self.setch(col, row, ch[0], ch[1], ch[2])
          col += 1
        
        row += 1
      
      col = 0
      while col < self.width:
        self.setch(col, self.height-1, " ", self.fg, self.bg)
        col += 1
      
      self.setcsr(0,self.height-1)
  
  def addstr(self, s):
    idx = 0
    for idx in range(len(s)):
      self.addch(s[idx])

# Text - A basic widget that displays a string.
class Text(Widget):
  def __init__(self, col, row, width, fg=CWHITE, bg=CBLACK, txt=""):
    Widget.__init__(self, col, row, width, 1)
    self.fg = fg
    self.bg = bg
    self.txt = txt
    self.settext(self.txt)
  
  def settext(self, txt):
    self.txt = txt
    
    # Render to internal buffer
    self.clear(" ", self.fg, self.bg)
    tmp = self.txt
    l = min(len(self.txt), self.width)
    if l < len(tmp):
      tmp = tmp[0:l]
    elif l > len(tmp):
      tmp = tmp+(" "*(l-len(tmp)))
    
    for idx in range(l):
      self.setch(idx,0,tmp[idx],self.fg,self.bg)
  
  def gettext(self):
    return self.txt

# TextEdit - A Text Widget extended with editing functionality.
class TextEdit(Text):
  pass

# MultiText - A Multi-Line equivalent of Text.
class MultiText(Widget):
  pass

# ScrollText - A MultiText with vertical scrolling capability.
class ScrollText(Widget):
  pass
